\section{Un ejemplo mas complejo}

Se requiere calcular una formula sencilla $(a*b)/c$. 
Lo que el metaprograma debe hace es: seleccionar alguna formula equivalente dependiendo de 
el rango de las variables $a,b,c$. Es decir las variables no solo son un valor arbitrario sino 
que también sabemos que pertenecen a cierto rango. $a \in (Ra_i,Ra_e)$, $b \in (Rb_i,Rb_e)$,
 $c \in (Rc_i,Rc_e)$.

\paragraph{}
Los rangos de las variables son conocidos en tiempo de compilación. Estos rangos conocidos en tiempo de compilación son útiles a la hora de elegir que variante de  $(a*b)/c$ (pej: $a*(b/c)$, $(a*b)*(1/c)$ , etc) el metaprograma seleccionará para generar el código mas apropiado. 

\paragraph{}
TODO: poner las reglas y que equivalencia queremos que genere.

\paragraph{}
Aquí vemos un claro escenario en donde un metaprograma ofrece una solución elegante. 
Existen variables en tiempo de ejecución $(a,b,c)$, los rangos que son variables en 
tiempo de compilación (se conocen a priori). El metaprograma debe generar el código mas apropiado, 
siguiendo los requerimientos citados, a partir de los rangos especificados de cada variable.

\paragraph{}
Veamos algunas definiciones antes de ver el código del metaprograma.

\paragraph{}
Lo primero que definiremos es un contenedor para nuestras tres variables y tres geters
\src{C++}{src/variables.h}

\paragraph{}


\paragraph{}
Es necesario definir algunos tipos de datos para poder trabajar, también geters para para poder accederlos:
\src{Haskell}{src/basicdata.phs}

$Range$, es nuestro tipo de dato mas importante contiene un rango y la variable que vive en ese rango (el geter a la variable). 
Después tenemos que tener una manera de expresar las divisiones y multiplicaciones, elegimos hacerlo con 
el tipo de dato recurrente $Exp$. Por ultimo definimos una regla $Rule$, una regla es un tipo de dato que 
contiene dos valores, el primeo es una función que toma tres rangos y devuelve \textbf{true} si esa regla debe aplicarse
para esos dos rangos; el segundo tipo de dato es una $Exp$ que contiene la formula equivalente a $a*b/c$a evaluarse si esa regla se cumple.  
\\
\\
Ahora que tenemos los tipos de datos básicos para nuestra librería activa, 
vamos a definir funciones auxiliares que nos harán la vida mas fácil.
\\
\\
\paragraph{}
\src{Haskell}{src/basicdefs.phs}
\paragraph{}
Ahora estamos en condiciones de escribir las reglas. Vamos a escribir una lista de $Rules$
con todas las reglas validas. 
\\
\\
\paragraph{}
\src{Haskell}{src/basicrules.phs}
\paragraph{}
Por ultimo, vamos a escribir una función que dado tres rangos, busque la primer regla valida y devuelva
la $Exp$ equivalente a $(a*b/c)$, para después evaluarla.
\\
\\
\paragraph{}
\src{Haskell}{src/basiclookup.phs}
\paragraph{}

Hasta ahora tenemos desarrollado en pHaskell, funciones y tipos de datos que nos ayudan a seleccionar 
una expresión a partir de tres rangos.\\
Ahora tenemos que escribir alguna forma de generar código a partir de este cálculo, para ello vamos a escribir las generatrices:
\\
\\
\paragraph{}
\src{Haskell}{src/basicgen.phs}
\paragraph{}


\subsection{Usando la librería activa}
Por ultimo vamos a llamar la generatriz como si fuéramos un usuario de la librería activa:
\\
\\
\paragraph{}
\src{Haskell}{src/basicmain.cpp}
\paragraph{}
 
\subsection{El código completo de la librería activa}
\paragraph{}
\src{Haskell}{src/basic.phs}